/*
用来做数据库缓存。
对象内存缓存。直接使用进程内存，没有跨进程通讯。
特点： 算法简单，释放高效。
未完善，需要加内存池，改为模板对象，才好复用。
*/
#include <functional>
#include <limits>
#include <queue>
#include <string>
#include <vector>
#include <unordered_map>
#include <iterator>  
#include <type_traits>
#include <memory>
#include <array>
#include <set>
#include <unordered_set>
#include "log_def.h"


//#define L_ASSERT(x) //如果担心指针安全，就写一个检查

//优化： 可是改为内存池分配ObjExample
struct ObjExample
{

};

template<class Obj = ObjExample>
class MemCache
{
	static const uint32 MAX_OBJ_NUM = 3;
	static const uint32 RELEASE_NUM = 1; //满后，每次释放数量 1

	std::unordered_map<uint64, Obj*> m_id2obj; //缓存对象
	std::deque<uint64> m_deque; //创建顺序 由旧 到 新

public:
	template <class... _Valtys>
	Obj* New(uint64 id, _Valtys&&... _Vals)
	{
		if (m_id2obj.size() >= MAX_OBJ_NUM)
		{
			ReleaseSome();
		}
		Obj* p = new Obj(std::forward<_Valtys>(_Vals)...);
		auto r = m_id2obj.emplace(id, p);
		if (!r.second)
		{
			delete p;
			return nullptr;
		}
		m_deque.push_back(id);
		return p;
	}

	//注意： 从deque后面开始查找， 刚创建对象执行删除，才能保证高效
	void Del(uint64 id)
	{
		for (auto it = m_deque.cbegin(); it != m_deque.cend(); ++it)
		{
			if ((*it) == id)
			{
				m_id2obj.erase(id);
				m_deque.erase(it);
				return;
			}
		}
	}

	Obj* Find(uint64 id)
	{
		auto it = m_id2obj.find(id);
		if (it == m_id2obj.end())
		{
			return nullptr;
		}
		return it->second;
	}
private:
	//删除部分对象。
	void ReleaseSome()
	{
		for (int i = 0; i < RELEASE_NUM; i++)
		{
			if (m_deque.empty())
			{
				return;
			}
			m_id2obj.erase(m_deque.front());
			m_deque.pop_front();
		}
	}

};